package exception

import "fmt"

// 基础错误类型
type ScriptError interface {
	Error() string
	Location() (line int, column int)
}

// 词法分析错误
type LexerError struct {
	Message string
	Code    int
	File    string
	Line    int //行号
	Column  int //列号
}

func (e *LexerError) Error() string {
	return fmt.Sprintf("[LexError %d:%d] %s", e.Line, e.Column, e.Message)
}

func (e *LexerError) Location() (int, int) {
	return e.Line, e.Column
}

// 语法分析错误
type ParseError struct {
	Message  string
	Code     int
	File     string
	Line     int      //行号
	Column   int      //列号
	Expected []string // 期望的token类型
}

func (e *ParseError) Error() string {
	expect := ""
	if len(e.Expected) > 0 {
		expect = fmt.Sprintf(", expected: %v", e.Expected)
	}
	return fmt.Sprintf("[ParseError %d:%d] %s%s", e.Line, e.Column, e.Message, expect)
}

// 运行时错误
type RuntimeError struct {
	Message string
	Code    int
	File    string
	Line    int         //行号
	Column  int         //列号
	Stack   []CallFrame // 调用栈信息
}

func (e *RuntimeError) Error() string {
	stackTrace := ""
	for _, frame := range e.Stack {
		stackTrace += fmt.Sprintf("\n  at %s(%d:%d)", frame.FunctionName, frame.Line, frame.Column)
	}
	return fmt.Sprintf("[RuntimeError %d:%d] %s%s", e.Line, e.Column, e.Message, stackTrace)
}

// 调用栈帧
type CallFrame struct {
	FunctionName string
	Line         int
	Column       int
}
